use async_trait::async_trait;
use rustcloud_core::{ServiceResult, ServiceError};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use tokio::sync::RwLock;

/// 指标类型枚举
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum MetricType {
    /// 计数器 - 只能增加的数值
    Counter,
    /// 测量仪 - 可增可减的数值
    Gauge,
    /// 直方图 - 观察值的分布
    Histogram,
    /// 汇总指标 - 提供分位数统计
    Summary,
}

/// 指标值
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum MetricValue {
    Counter(f64),
    Gauge(f64),
    Histogram {
        count: u64,
        sum: f64,
        buckets: Vec<(f64, u64)>, // (upper_bound, count)
    },
    Summary {
        count: u64,
        sum: f64,
        quantiles: Vec<(f64, f64)>, // (quantile, value)
    },
}

/// 指标标签
pub type Labels = HashMap<String, String>;

/// 单个指标数据
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Metric {
    /// 指标名称
    pub name: String,
    /// 指标帮助信息
    pub help: String,
    /// 指标类型
    pub metric_type: MetricType,
    /// 指标值
    pub value: MetricValue,
    /// 指标标签
    pub labels: Labels,
    /// 时间戳
    pub timestamp: SystemTime,
}

impl Metric {
    pub fn new(name: String, help: String, metric_type: MetricType, value: MetricValue) -> Self {
        Self {
            name,
            help,
            metric_type,
            value,
            labels: HashMap::new(),
            timestamp: SystemTime::now(),
        }
    }

    pub fn with_labels(mut self, labels: Labels) -> Self {
        self.labels = labels;
        self
    }

    pub fn with_label(mut self, key: String, value: String) -> Self {
        self.labels.insert(key, value);
        self
    }
}

/// 指标系列（一组具有相同名称但不同标签的指标）
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricFamily {
    pub name: String,
    pub help: String,
    pub metric_type: MetricType,
    pub metrics: Vec<Metric>,
}

/// 指标收集器trait
#[async_trait]
pub trait MetricsCollector: Send + Sync {
    /// 注册一个新的指标
    async fn register_metric(&self, name: &str, help: &str, metric_type: MetricType, labels: Labels) -> ServiceResult<()>;
    
    /// 记录计数器值
    async fn record_counter(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()>;
    
    /// 设置测量仪值
    async fn set_gauge(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()>;
    
    /// 增加测量仪值
    async fn inc_gauge(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()>;
    
    /// 减少测量仪值
    async fn dec_gauge(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()>;
    
    /// 观察直方图值
    async fn observe_histogram(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()>;
    
    /// 观察汇总值
    async fn observe_summary(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()>;
    
    /// 获取所有指标
    async fn gather(&self) -> ServiceResult<Vec<MetricFamily>>;
    
    /// 重置所有指标
    async fn reset(&self) -> ServiceResult<()>;
}

/// 内存指标收集器
pub struct MemoryMetricsCollector {
    metrics: Arc<RwLock<HashMap<String, MetricFamily>>>,
}

impl MemoryMetricsCollector {
    pub fn new() -> Self {
        Self {
            metrics: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    /// 生成指标键
    fn generate_metric_key(name: &str, labels: &Labels) -> String {
        let mut key = name.to_string();
        if !labels.is_empty() {
            let mut label_pairs: Vec<_> = labels.iter().collect();
            label_pairs.sort_by_key(|&(k, _)| k);
            key.push('{');
            for (i, (k, v)) in label_pairs.iter().enumerate() {
                if i > 0 {
                    key.push(',');
                }
                key.push_str(&format!("{}={}", k, v));
            }
            key.push('}');
        }
        key
    }

    /// 获取或创建指标族
    async fn get_or_create_family(&self, name: &str, help: &str, metric_type: MetricType) -> ServiceResult<()> {
        let mut metrics = self.metrics.write().await;
        if !metrics.contains_key(name) {
            metrics.insert(name.to_string(), MetricFamily {
                name: name.to_string(),
                help: help.to_string(),
                metric_type,
                metrics: Vec::new(),
            });
        }
        Ok(())
    }

    /// 更新或添加指标
    async fn update_metric(&self, name: &str, labels: Labels, value: MetricValue) -> ServiceResult<()> {
        let mut metrics = self.metrics.write().await;
        if let Some(family) = metrics.get_mut(name) {
            // 查找是否已存在相同标签的指标
            if let Some(metric) = family.metrics.iter_mut().find(|m| m.labels == labels) {
                metric.value = value;
                metric.timestamp = SystemTime::now();
            } else {
                // 创建新指标
                family.metrics.push(Metric {
                    name: name.to_string(),
                    help: family.help.clone(),
                    metric_type: family.metric_type.clone(),
                    value,
                    labels,
                    timestamp: SystemTime::now(),
                });
            }
        } else {
            return Err(ServiceError::MetricsError(format!("Metric family '{}' not found", name)));
        }
        Ok(())
    }
}

#[async_trait]
impl MetricsCollector for MemoryMetricsCollector {
    async fn register_metric(&self, name: &str, help: &str, metric_type: MetricType, _labels: Labels) -> ServiceResult<()> {
        self.get_or_create_family(name, help, metric_type).await
    }

    async fn record_counter(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()> {
        // 对于计数器，我们累加值
        let metrics = self.metrics.read().await;
        if let Some(family) = metrics.get(name) {
            if family.metric_type != MetricType::Counter {
                return Err(ServiceError::MetricsError(format!("Metric '{}' is not a counter", name)));
            }
            
            drop(metrics); // 释放读锁
            
            // 获取当前值并累加
            let mut metrics = self.metrics.write().await;
            if let Some(family) = metrics.get_mut(name) {
                if let Some(metric) = family.metrics.iter_mut().find(|m| m.labels == labels) {
                    if let MetricValue::Counter(current) = metric.value {
                        metric.value = MetricValue::Counter(current + value);
                        metric.timestamp = SystemTime::now();
                    }
                } else {
                    // 创建新的计数器指标
                    family.metrics.push(Metric {
                        name: name.to_string(),
                        help: family.help.clone(),
                        metric_type: MetricType::Counter,
                        value: MetricValue::Counter(value),
                        labels,
                        timestamp: SystemTime::now(),
                    });
                }
            }
        } else {
            return Err(ServiceError::MetricsError(format!("Counter '{}' not registered", name)));
        }
        Ok(())
    }

    async fn set_gauge(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()> {
        self.update_metric(name, labels, MetricValue::Gauge(value)).await
    }

    async fn inc_gauge(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()> {
        let metrics = self.metrics.read().await;
        if let Some(family) = metrics.get(name) {
            if family.metric_type != MetricType::Gauge {
                return Err(ServiceError::MetricsError(format!("Metric '{}' is not a gauge", name)));
            }
            
            drop(metrics);
            
            let mut metrics = self.metrics.write().await;
            if let Some(family) = metrics.get_mut(name) {
                if let Some(metric) = family.metrics.iter_mut().find(|m| m.labels == labels) {
                    if let MetricValue::Gauge(current) = metric.value {
                        metric.value = MetricValue::Gauge(current + value);
                        metric.timestamp = SystemTime::now();
                    }
                } else {
                    family.metrics.push(Metric {
                        name: name.to_string(),
                        help: family.help.clone(),
                        metric_type: MetricType::Gauge,
                        value: MetricValue::Gauge(value),
                        labels,
                        timestamp: SystemTime::now(),
                    });
                }
            }
        } else {
            return Err(ServiceError::MetricsError(format!("Gauge '{}' not registered", name)));
        }
        Ok(())
    }

    async fn dec_gauge(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()> {
        self.inc_gauge(name, -value, labels).await
    }

    async fn observe_histogram(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()> {
        // 简化的直方图实现，使用固定的桶
        let buckets = vec![0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, f64::INFINITY];
        
        let metrics = self.metrics.read().await;
        if let Some(family) = metrics.get(name) {
            if family.metric_type != MetricType::Histogram {
                return Err(ServiceError::MetricsError(format!("Metric '{}' is not a histogram", name)));
            }
            
            drop(metrics);
            
            let mut metrics = self.metrics.write().await;
            if let Some(family) = metrics.get_mut(name) {
                if let Some(metric) = family.metrics.iter_mut().find(|m| m.labels == labels) {
                    if let MetricValue::Histogram { count, sum, buckets: ref mut metric_buckets } = &mut metric.value {
                        *count += 1;
                        *sum += value;
                        
                        // 更新桶计数
                        for (i, &bucket_upper) in buckets.iter().enumerate() {
                            if value <= bucket_upper {
                                if i < metric_buckets.len() {
                                    metric_buckets[i].1 += 1;
                                } else {
                                    metric_buckets.push((bucket_upper, 1));
                                }
                                break;
                            }
                        }
                        metric.timestamp = SystemTime::now();
                    }
                } else {
                    // 创建新的直方图指标
                    let mut histogram_buckets = Vec::new();
                    for &bucket_upper in &buckets {
                        let count = if value <= bucket_upper { 1 } else { 0 };
                        histogram_buckets.push((bucket_upper, count));
                    }
                    
                    family.metrics.push(Metric {
                        name: name.to_string(),
                        help: family.help.clone(),
                        metric_type: MetricType::Histogram,
                        value: MetricValue::Histogram {
                            count: 1,
                            sum: value,
                            buckets: histogram_buckets,
                        },
                        labels,
                        timestamp: SystemTime::now(),
                    });
                }
            }
        } else {
            return Err(ServiceError::MetricsError(format!("Histogram '{}' not registered", name)));
        }
        Ok(())
    }

    async fn observe_summary(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()> {
        // 简化的汇总实现
        let metrics = self.metrics.read().await;
        if let Some(family) = metrics.get(name) {
            if family.metric_type != MetricType::Summary {
                return Err(ServiceError::MetricsError(format!("Metric '{}' is not a summary", name)));
            }
            
            drop(metrics);
            
            let mut metrics = self.metrics.write().await;
            if let Some(family) = metrics.get_mut(name) {
                if let Some(metric) = family.metrics.iter_mut().find(|m| m.labels == labels) {
                    if let MetricValue::Summary { count, sum, .. } = &mut metric.value {
                        *count += 1;
                        *sum += value;
                        metric.timestamp = SystemTime::now();
                    }
                } else {
                    family.metrics.push(Metric {
                        name: name.to_string(),
                        help: family.help.clone(),
                        metric_type: MetricType::Summary,
                        value: MetricValue::Summary {
                            count: 1,
                            sum: value,
                            quantiles: vec![
                                (0.5, value),  // 中位数
                                (0.9, value),  // 90分位数
                                (0.99, value), // 99分位数
                            ],
                        },
                        labels,
                        timestamp: SystemTime::now(),
                    });
                }
            }
        } else {
            return Err(ServiceError::MetricsError(format!("Summary '{}' not registered", name)));
        }
        Ok(())
    }

    async fn gather(&self) -> ServiceResult<Vec<MetricFamily>> {
        let metrics = self.metrics.read().await;
        Ok(metrics.values().cloned().collect())
    }

    async fn reset(&self) -> ServiceResult<()> {
        let mut metrics = self.metrics.write().await;
        metrics.clear();
        Ok(())
    }
}

impl Default for MemoryMetricsCollector {
    fn default() -> Self {
        Self::new()
    }
}

/// 便利方法用于创建标签
pub fn labels() -> Labels {
    HashMap::new()
}

pub fn labels_from_pairs(pairs: &[(impl AsRef<str>, impl AsRef<str>)]) -> Labels {
    pairs.iter()
        .map(|(k, v)| (k.as_ref().to_string(), v.as_ref().to_string()))
        .collect()
}

/// 指标构建器
pub struct MetricsBuilder {
    collector: Arc<dyn MetricsCollector>,
}

impl MetricsBuilder {
    pub fn new(collector: Arc<dyn MetricsCollector>) -> Self {
        Self { collector }
    }

    /// 创建计数器
    pub async fn counter(&self, name: &str, help: &str) -> ServiceResult<Counter> {
        self.collector.register_metric(name, help, MetricType::Counter, HashMap::new()).await?;
        Ok(Counter {
            name: name.to_string(),
            collector: self.collector.clone(),
        })
    }

    /// 创建测量仪
    pub async fn gauge(&self, name: &str, help: &str) -> ServiceResult<Gauge> {
        self.collector.register_metric(name, help, MetricType::Gauge, HashMap::new()).await?;
        Ok(Gauge {
            name: name.to_string(),
            collector: self.collector.clone(),
        })
    }

    /// 创建直方图
    pub async fn histogram(&self, name: &str, help: &str) -> ServiceResult<Histogram> {
        self.collector.register_metric(name, help, MetricType::Histogram, HashMap::new()).await?;
        Ok(Histogram {
            name: name.to_string(),
            collector: self.collector.clone(),
        })
    }

    /// 创建汇总
    pub async fn summary(&self, name: &str, help: &str) -> ServiceResult<Summary> {
        self.collector.register_metric(name, help, MetricType::Summary, HashMap::new()).await?;
        Ok(Summary {
            name: name.to_string(),
            collector: self.collector.clone(),
        })
    }
}

/// 计数器
pub struct Counter {
    name: String,
    collector: Arc<dyn MetricsCollector>,
}

impl Counter {
    pub async fn inc(&self) -> ServiceResult<()> {
        self.inc_by(1.0).await
    }

    pub async fn inc_by(&self, value: f64) -> ServiceResult<()> {
        self.collector.record_counter(&self.name, value, HashMap::new()).await
    }

    pub async fn inc_with_labels(&self, value: f64, labels: Labels) -> ServiceResult<()> {
        self.collector.record_counter(&self.name, value, labels).await
    }
}

/// 测量仪
pub struct Gauge {
    name: String,
    collector: Arc<dyn MetricsCollector>,
}

impl Gauge {
    pub async fn set(&self, value: f64) -> ServiceResult<()> {
        self.collector.set_gauge(&self.name, value, HashMap::new()).await
    }

    pub async fn set_with_labels(&self, value: f64, labels: Labels) -> ServiceResult<()> {
        self.collector.set_gauge(&self.name, value, labels).await
    }

    pub async fn inc(&self) -> ServiceResult<()> {
        self.inc_by(1.0).await
    }

    pub async fn inc_by(&self, value: f64) -> ServiceResult<()> {
        self.collector.inc_gauge(&self.name, value, HashMap::new()).await
    }

    pub async fn dec(&self) -> ServiceResult<()> {
        self.dec_by(1.0).await
    }

    pub async fn dec_by(&self, value: f64) -> ServiceResult<()> {
        self.collector.dec_gauge(&self.name, value, HashMap::new()).await
    }
}

/// 直方图
pub struct Histogram {
    name: String,
    collector: Arc<dyn MetricsCollector>,
}

impl Histogram {
    pub async fn observe(&self, value: f64) -> ServiceResult<()> {
        self.collector.observe_histogram(&self.name, value, HashMap::new()).await
    }

    pub async fn observe_with_labels(&self, value: f64, labels: Labels) -> ServiceResult<()> {
        self.collector.observe_histogram(&self.name, value, labels).await
    }

    /// 计时器 - 测量代码块执行时间
    pub async fn time<F, Fut, T>(&self, func: F) -> ServiceResult<T>
    where
        F: FnOnce() -> Fut,
        Fut: std::future::Future<Output = T>,
    {
        let start = SystemTime::now();
        let result = func().await;
        if let Ok(duration) = start.elapsed() {
            self.observe(duration.as_secs_f64()).await?;
        }
        Ok(result)
    }
}

/// 汇总
pub struct Summary {
    name: String,
    collector: Arc<dyn MetricsCollector>,
}

impl Summary {
    pub async fn observe(&self, value: f64) -> ServiceResult<()> {
        self.collector.observe_summary(&self.name, value, HashMap::new()).await
    }

    pub async fn observe_with_labels(&self, value: f64, labels: Labels) -> ServiceResult<()> {
        self.collector.observe_summary(&self.name, value, labels).await
    }
}